package com.nit.lab.vote.service.vote.impl;

import com.nit.lab.vote.dto.utils.PagingDTO;
import com.nit.lab.vote.dto.utils.TableReqDTO;
import com.nit.lab.vote.dto.utils.TableRspDTO;
import com.nit.lab.vote.dto.vote.CPDTO;
import com.nit.lab.vote.dto.vote.CandidateDTO;
import com.nit.lab.vote.dto.utils.OpResultDTO;
import com.nit.lab.vote.entity.vote.CPEntity;
import com.nit.lab.vote.entity.vote.CandidateEntity;
import com.nit.lab.vote.mapper.vote.CandidateMapper;
import com.nit.lab.vote.service.vote.CandidateService;
import com.nit.lab.vote.utils.UploadFileUtil;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

@Service
public class CandidateServiceImpl implements CandidateService {
    @Autowired(required = false)
    private CandidateMapper candidateMapper;

    @Override
    public TableRspDTO list4table(TableReqDTO tableRepDTO) throws Exception {
        String projectIdStr = tableRepDTO.parseQueryParam("projectId");
        Long projectId = projectIdStr == null ? null : Long.valueOf(projectIdStr);
        Long count = candidateMapper.count4Table1(
                tableRepDTO.parseQueryParam("candidateName")
        );
        PagingDTO pagingDTO = new PagingDTO(
                tableRepDTO.getPageNo(),
                tableRepDTO.getPageSize(),
                count,
                candidateMapper.list4Table(
                        tableRepDTO.parseQueryParam("candidateName"),
                        tableRepDTO.getStart(),
                        tableRepDTO.getPageSize(),
                        tableRepDTO.getSortField(),
                        tableRepDTO.getSortOrder()));
        return new TableRspDTO(pagingDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO add(CandidateDTO candidateDTO) throws Exception {
        OpResultDTO op = new OpResultDTO();
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        CandidateEntity candidateEntity = mapperFactory.getMapperFacade().map(candidateDTO, CandidateEntity.class);
        candidateEntity.setGmtCreate(new Date(System.currentTimeMillis()));
        op.setResult(candidateMapper.add(candidateEntity));
        return op;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO update(CandidateDTO candidateDTO) throws Exception {
        OpResultDTO op = new OpResultDTO();
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        CandidateEntity candidateEntity = mapperFactory.getMapperFacade().map(candidateDTO, CandidateEntity.class);
        op.setResult(candidateMapper.update(candidateEntity));
        return op;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO remove(CandidateDTO candidateDTO) throws Exception {
        OpResultDTO op = new OpResultDTO();
        op.setResult(candidateMapper.remove(candidateDTO.getCandidateId()));
        return op;
    }



    @Override
    public TableRspDTO queryByProject(TableReqDTO tableRepDTO) throws Exception {
        String projectIdStr = tableRepDTO.parseQueryParam("projectId");
        PagingDTO pagingDTO;
        if (projectIdStr == null) {
            throw new IllegalArgumentException("Lose projectId");
        } else {
            Long projectId = Long.valueOf(projectIdStr);
            Long count = candidateMapper.countByProject(
                    tableRepDTO.parseQueryParam("candidateName"),
                    null,
                    projectId);
            List<CandidateDTO> candidateDTOS = candidateMapper.listByProject(
                    tableRepDTO.parseQueryParam("candidateName"),
                    null,
                    projectId,
                    tableRepDTO.getStart(),
                    tableRepDTO.getPageSize(),
                    tableRepDTO.getSortField(),
                    tableRepDTO.getSortOrder());
            for (CandidateDTO candidateDTO: candidateDTOS) {
                StringBuilder fileAddr = new StringBuilder();
                for (String str: candidateMapper.getFilesByCPId(candidateDTO.getKey())) {
                    if (!fileAddr.toString().equals("")) {
                        fileAddr.append(",");
                    }
                    fileAddr.append(str);
                }
                candidateDTO.setFileAddr(fileAddr.toString());
            }
            pagingDTO = new PagingDTO(
                    tableRepDTO.getPageNo(),
                    tableRepDTO.getPageSize(),
                    count,
                    candidateDTOS);
            return new TableRspDTO(pagingDTO);
        }
    }

    @Override
    public TableRspDTO queryAllProject(TableReqDTO tableRepDTO) throws Exception {
        String projectIdStr = tableRepDTO.parseQueryParam("projectId");
        PagingDTO pagingDTO;
        if (projectIdStr == null) {
            throw new IllegalArgumentException("Lose projectId");
        } else {
            Long projectId = Long.valueOf(projectIdStr);
            Long count = candidateMapper.countAllProject(
                    tableRepDTO.parseQueryParam("candidateName")
            );
            pagingDTO = new PagingDTO(
                    tableRepDTO.getPageNo(),
                    tableRepDTO.getPageSize(),
                    count,
                    candidateMapper.listAllProject(
                            tableRepDTO.parseQueryParam("candidateName"),
                            projectId,
                            tableRepDTO.getStart(),
                            tableRepDTO.getPageSize(),
                            tableRepDTO.getSortField(),
                            tableRepDTO.getSortOrder()));
            return new TableRspDTO(pagingDTO);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO addByProject(CPDTO cpDTO) throws Exception {
        OpResultDTO op = new OpResultDTO();
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        CPEntity cpEntity = mapperFactory.getMapperFacade().map(cpDTO, CPEntity.class);
        op.setResult(candidateMapper.addByProject(cpEntity));
        return op;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO removeByProject(CPDTO cpDTO) throws Exception {
        OpResultDTO op = new OpResultDTO();
        op.setResult(candidateMapper.removeByProject(cpDTO.getProjectId(), cpDTO.getCandidateId()));
        return op;
    }



    @Override
    public OpResultDTO queryFile(CPDTO cpDTO) throws Exception {
        OpResultDTO op = new OpResultDTO();
        Long cpId = candidateMapper.getCPId(cpDTO.getProjectId(), cpDTO.getCandidateId());
        if (cpId != null) {
            List<String> strings = candidateMapper.getFiles(cpId);
            StringBuilder fileAddr = new StringBuilder();
            for (String str: strings) {
                if (!fileAddr.toString().equals("")) {
                    fileAddr.append(",");
                }
                fileAddr.append(str);
            }
            op.setResult(fileAddr.toString());
        } else {
            op.setMessage("error");
            op.setResult("信息有误，请确保候选人已参加项目");
        }
        return op;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO addFile(CPDTO cpDTO, MultipartFile file) throws Exception {
        OpResultDTO op = new OpResultDTO();
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        CPEntity cpEntity = mapperFactory.getMapperFacade().map(cpDTO, CPEntity.class);
        Long cpId = candidateMapper.getCPId(cpEntity.getProjectId(), cpEntity.getCandidateId());
        if (cpId != null) {
            CandidateDTO candidateDTO = candidateMapper.getCandidateById(cpDTO.getCandidateId());
            String relativePath = "/" + candidateDTO.getCandidateName() + candidateDTO.getEmployeeNumber()
                + "/" + cpDTO.getProjectId();
            String url = UploadFileUtil.uploadFile(file, relativePath);
            if (url == null) {
                op.setMessage("error");
                op.setResult("文件已存在");
            } else {
                candidateMapper.addFile(cpId, url);
                op.setResult(url);
            }
        } else {
            op.setMessage("error");
            op.setResult("信息有误，请确保候选人已参加项目");
        }
        return op;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OpResultDTO removeFile(String file) throws Exception {
        OpResultDTO op = new OpResultDTO();
        UploadFileUtil.deleteTempFile(file);
        op.setResult(candidateMapper.removeFile(file));
        return op;
    }
}
